﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Linq;
using log4net;
using System.IO;

namespace GenerateDB
{
    /// <summary>
    /// Проверка XML файла по его XSD описанию
    /// </summary>
    class XMLCheckerByXSD
    {
        /// <summary>
        /// Проверяемый XML файл
        /// </summary>
        private string _xmlFile;

        private string _xsdScheme;

        private Settings _settings;
        private static readonly ILog _log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        /// <summary>
        /// Проверка XML файла по его XSD описани
        /// </summary>
        /// <param name="xmlFile">Проверяемый XML файл</param>
        public XMLCheckerByXSD(string xmlFile, string xsdScheme)
        {
            this.Init(xmlFile, xsdScheme);
        }

        /// <summary>
        /// Инициализации
        /// </summary>
        /// <param name="xmlFile">Проверяемый XML файл</param>
        private void Init(string xmlFile, string xsdScheme)
        {
            _xmlFile = xmlFile;
            _xsdScheme = xsdScheme;
            _settings = new Settings();
            
        }
        /// <summary>
        /// Проверить XML файл.
        /// </summary>
        /// <returns>Возвращает true, если файл не содержи ошибок, иначе false</returns>
        public void Check()
        {
            try
            {
                XmlSchemaSet schemaSet = new XmlSchemaSet();
                schemaSet.Add(_settings.TargetNamespace, _xsdScheme);

                XmlSchema compiledSchema = null;
                foreach (XmlSchema schema in schemaSet.Schemas())
                {
                    compiledSchema = schema;
                }

                XmlReaderSettings settings = new XmlReaderSettings();
                settings.Schemas.Add(compiledSchema);
                settings.ValidationType = ValidationType.Schema;
                settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
                settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
                settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
                settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

                //Create the schema validating reader.
                XmlReader vreader = XmlReader.Create(_xmlFile, settings);

                while (vreader.Read()) { }

                //Close the reader.
                vreader.Close();
            }
            catch (XmlSchemaException ex)
            {
                string error = "Ошибка проверки XML файла.";
                _log.Error(error, ex);
                throw new Exception(error + " Подробнее: " + ex.Message);
            }
        }

        /// <summary>
        /// Выбрасывается сиключения, если есть ошибка или предупреждение
        /// </summary>
        private static void ValidationCallBack(object sender, ValidationEventArgs args)
        {
            if (args.Severity == XmlSeverityType.Warning)
            {
                string warning = String.Format("Validation xml warning: {0}", args.Message);
                _log.Warn(warning);
                throw new Exception(warning);
            }
            else
            {
                string error = String.Format("Validation xml error: {0}", args.Message);
                _log.Error(error);
                throw new Exception(error);
            }

        }
    }
}
